package com.gjs.common.manager.storage;

import cn.hutool.json.JSONUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 阿里云OSS封装类
 *
 * @author JC_Ho
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AliyunOss {

    /**
     * AccessId
     */
    private String accessId;

    /**
     * AccessKey
     */
    private String accessKey;

    /**
     * Endpoint
     */
    private String endpoint;

    /**
     * Bucket名称
     */
    private String bucket;

    /**
     * Host名称
     * 默认格式为https://bucketname.endpoint。
     */
    private String host;

    /**
     * 上传回调URL，即回调服务器地址，用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后，把文件上传信息通过此回调URL发送给应用服务器。
     */
    private String callbackUrl;

    /**
     * 上传到OSS文件的前缀，可置空此项。置空后，文件将上传至Bucket的根目录下。
     */
    private String dir;

    public Map<String, String> getUploadPolicy() throws Exception {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(this.getEndpoint(), this.getAccessId(), this.getAccessKey());
        Map<String, String> respMap = new LinkedHashMap<>();
        try {
            long expireTime = 300;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            // PostObject请求最大可支持的文件大小为5 GB，即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, this.getDir());

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            respMap.put("accessid", this.getAccessId());
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", this.getDir());
            respMap.put("host", this.getHost());
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
            // respMap.put("expire", formatISO8601Date(expiration));

            Map<String, String> callback = new LinkedHashMap<>();
            callback.put("callbackUrl", this.getCallbackUrl());
            callback.put("callbackBody", "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
            callback.put("callbackBodyType", "application/x-www-form-urlencoded");
            String base64CallbackBody = BinaryUtil.toBase64String(JSONUtil.toJsonStr(callback).getBytes());

            // 因为暂时没有回调服务器，所以先不传
//            respMap.put("callback", base64CallbackBody);

        } catch (Exception e) {
            throw new Exception(e.getMessage());
        } finally {
            ossClient.shutdown();
        }

        return respMap;
    }
}
